TagManager = function( domElem )
{
    ///////////////////////////////////////////////////////////////////////////
    // private functions
    ///////////////////////////////////////////////////////////////////////////
    this.onClick = function( event )
    {
        var tagManager = event.currentTarget.tagManager;
        var curID      = event.currentTarget.id;

        tagManager.m_tags[curID].state = (tagManager.m_tags[curID].state+1) % tagManager.m_stateClasses.length;
        tagManager.updateElemView( curID );

        $(tagManager).trigger( 'onchange', [curID, tagManager.m_tags[curID].state] );
    }

    this.updateElemView = function( tag_id )
    {
        var tagElem = null;
        for ( var k = 0; k < this.m_domElem.childNodes.length; k++ )
        {
            if ( this.m_domElem.childNodes[k].id == tag_id )
            {
                tagElem = this.m_domElem.childNodes[k];
                break;
            }
        }

        if ( tagElem == null ) return;
        
        $(tagElem).attr('class', this.m_stateClasses[this.m_tags[tag_id].state]);

        // if (this.m_tags[tag_id].state)
            // $(tagElem).removeClass( "inactive_tag" ).addClass("active_tag");
        // else
            // $(tagElem).removeClass( "active_tag" ).addClass("inactive_tag");
    }
    
    this.m_tags = [];
    this.m_domElem = domElem;
    this.m_stateClasses = [];

    domElem.innerHTML = '';
}

//all previous manager's data will be deleted
TagManager.prototype.setTagList = function( tagList, stateClasses, initialState )
{
    if ( tagList.length == 0 )
        this.m_domElem.innerHTML = 'No tags';
        
    //clone!
    this.m_stateClasses = stateClasses.slice(0);
    // for (var i in stateClasses)
    // {
        // this.m_stateClasses[i] = stateClasses[i];
        // this.m_statesCount++;
    // }
    
    this.m_tags = [];
    for ( var k = 0; k < tagList.length; k++ )
    {
        var curState = true;
        if ( typeof(tagList[k].state) != 'undefined' )
            curState = tagList[k].state;
        else if ( typeof( initialState ) != 'undefined' )
            curState = initialState;
        else 
        {
            alert('Missing initial state for tag' + tagList[k].tag);
            return;
        }
        
        if ( typeof(this.m_stateClasses[curState]) == 'undefined' )
        {
            alert('Missing state class for tag' + tagList[k].tag);
            return;
        }

        this.m_tags[tagList[k].id] = { state: curState, tag: tagList[k].tag };

        var curTagElem = document.createElement('b');
        var delim = document.createTextNode(" ");
        curTagElem.id = tagList[k].id;
        curTagElem.innerHTML = tagList[k].tag;
        curTagElem.onclick = this.onClick;

        curTagElem.tagManager = this;
        this.m_domElem.appendChild( curTagElem );
        this.m_domElem.appendChild( delim );
        this.updateElemView( tagList[k].id );
    }
    
    $(this).trigger( 'onchange', [null, null] );
}

TagManager.prototype.getStateByID = function( tag_id )
{
    return this.m_tags[ tag_id ].state;
}

TagManager.prototype.getIDsWithState = function( state )
{
    var listActive = [];
    for (var k in this.m_tags)
        if ( this.m_tags[k].state == state )
            listActive.push(k);
    return listActive;
}

//todo: can be precomputed
TagManager.prototype.getIDsWithStateAsHash = function( state )
{
    var hashActive = {};
    for (var k in this.m_tags)
        if ( this.m_tags[k].state == state )
            hashActive[k] = 1;
    return hashActive;
}

